home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
201-225
/
214
/
mandelvroom
/
src
/
mand.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
19KB
|
831 lines
/*
* MandelVroom 2.0
*
* (c) Copyright 1987,1989 Kevin L. Clague, San Jose, CA
*
* All rights reserved.
*
* Permission is hereby granted to distribute this program's source
* executable, and documentation for non-comercial purposes, so long as the
* copyright notices are not removed from the sources, executable or
* documentation. This program may not be distributed for a profit without
* the express written consent of the author Kevin L. Clague.
*
* This program is not in the public domain.
*
* Fred Fish is expressly granted permission to distribute this program's
* source and executable as part of the "Fred Fish freely redistributable
* Amiga software library."
*
* Permission is expressly granted for this program and it's source to be
* distributed as part of the Amicus Amiga software disks, and the
* First Amiga User Group's Hot Mix disks.
*
* contents: this file contains funtions to create, maintain and delete
* Mandelbrot and Julia projects (including spawning off child generator
* tasks.)
*/
#include "mandp.h"
struct NewWindow NewMand = {
0,12, /* start position */
80,80, /* width, height */
(UBYTE) 0, (UBYTE) NORMALPEN,
NULL, /* IDCMP flags */
/* MandWind flags */
WINDOWCLOSE | WINDOWDEPTH | WINDOWSIZING | WINDOWDRAG | ACTIVATE |
REPORTMOUSE | NOCAREREFRESH | SMART_REFRESH,
(struct Gadget *) NULL, /* first gadget */
(struct Image *) NULL, /* user checkmark */
(UBYTE *) NULL, /* Title */
(struct Screen *) NULL, /* pointer to screen */
(struct BitMap *) NULL, /* pointer to superbitmap */
20,20,-1,-1, /* sizing */
CUSTOMSCREEN /* type of screen */
};
LONG TopMarg = 10;
LONG BotMarg = 2;
LONG LeftMarg = 2;
LONG RightMarg;
ULONG CalcTime;
extern LONG TaskPri, MainPri;
extern LONG pSigMask;
extern struct ExecBase *ExecBase;
static struct Picture *GenNPict;
/* Toggle generation of project */
GenerateCmd(Msg)
struct IntuiMessage *Msg;
{
switch(Msg->Class) {
case GADGETDOWN:
ToggleGen((struct Picture *) Msg->IDCMPWindow->UserData);
break;
case MENUPICK:
switch( SUBNUM(Msg->Code) ) {
case STARTGEN:
CurPict->GenState = GENPENDSTATE;
Generate( CurPict );
break;
case STOPGEN:
ThrowTask(CurPict);
break;
case CONTGEN:
CurPict->GenState = CONTINUESTATE;
Generate( CurPict );
break;
}
break;
}
}
ToggleGen( Pict )
struct Picture *Pict;
{
if ( Pict->gTask ) {
ThrowTask( Pict );
} else {
Pict->GenState = GENPENDSTATE;
Generate( Pict );
}
SetGenGad( Pict );
}
/*
* Generate It
*/
Generate( Pict )
register struct Picture *Pict;
{
register char *t;
int GenTask();
extern struct MenuItem LensSub[];
if ( Pict->gTask ) {
return;
}
if (Pict->Flags & SCROLL_HAPPENED) {
/* create a new counts array with unclipped data in it */
/* adjust the real and imaginary upper left */
ScrollComplex(Pict);
if (Pict->Counts == NULL)
return;
} else {
FreeScrollTemp(Pict);
if (Pict->GenState == CONTINUESTATE ){
if ( Pict->CurLine < Pict->CountY ) {
if (Pict->Counts == NULL) return;
} else {
return;
}
}
if (Pict->GenState == GENPENDSTATE) {
InitNewGen( Pict );
if (Pict->Counts == NULL) return;
}
}
ResetScrollRects(Pict);
Pict->GenState = GENERATESTATE;
if ( Pict->MathMode == INTIIGENERATOR &&
(ExecBase->AttnFlags & (1 << AFB_68020)) == 0 ) {
Pict->MathMode = INTGENERATOR;
}
if ( Pict->MathMode == _81GENERATOR &&
(ExecBase->AttnFlags & (1 << AFB_68881)) == 0 ) {
Pict->MathMode = IEEEGENERATOR;
}
MakeColorXlate( Pict );
if (Pict->MathMode == 1) {
if (OpenFFPLibs() != 0)
return;
}
/* Spawn off the generator as a task */
DateStamp( Pict->TimeStamp );
/* GenNPict is pointer to Picture that task needs to generate */
GenNPict = Pict;
#define KAY (1024L)
#ifdef MULTI
Pict->gTask = CreateTask( Pict->Title+2, MainPri, GenTask, KAY);
if ( Pict->gTask == NULL ) {
DispErrMsg("Could not create task",0);
}
SetGenGad( Pict );
/* Do this so we are sure child is done with GenNPict */
Wait( pSigMask );
#else
GenTask();
#endif
}
InitNewGen( Pict )
register struct Picture *Pict;
{
if (Pict->Flags & BORDERLESS_PROJ) {
Pict->LeftMarg = 0;
Pict->RightMarg = 0;
Pict->TopMarg = 0;
Pict->BotMarg = 0;
}
/* figure out new picture size */
Pict->CountX = Pict->Window->Width-(Pict->LeftMarg+Pict->RightMarg);
Pict->CountY = Pict->Window->Height-(Pict->TopMarg+Pict->BotMarg);
/* free up old counts memory, get new picture size, get new counts memory
*/
GetCountsMemory( Pict );
if (Pict->Counts == NULL) {
DispErrMsg("Can't generate. Out of RAM!!",0);
return;
}
if (Pict->Flags & NO_RAM_GENERATE ) {
DispErrMsg("Can't save counts. Out of RAM!!",0);
}
/* calculate new picture's coordinates from zoom box */
ZoomIn( Pict );
Pict->CurLine = 0;
/* clear the picture area */
if (!(Pict->Flags & LENS_DISPLAYED)) {
SetAPen( Pict->Window->RPort, NORMALPEN );
RectFill( Pict->Window->RPort, Pict->LeftMarg, Pict->TopMarg,
Pict->Window->Width - Pict->RightMarg - 1,
Pict->Window->Height - Pict->BotMarg - 1);
}
}
GenTask() {
register struct Picture *Pict;
int MandelbrotInt32();
int MandelbrotInt32II();
int MandelbrotIEEE();
int MandelbrotFFP();
int JuliaInt32();
int JuliaIEEE();
int JuliaFFP();
LONG SPFieee();
#ifdef MULTI
geta4();
#endif
Pict = GenNPict;
/* Signal Parent that we have accessed GenNPict */
Signal( mTask, pSigMask );
/* Lower our priority while we generate */
SetTaskPri( FindTask(0), TaskPri );
Pict->GenChildState = GENINCOMPLETE;
if (GetTaskSig( Pict ) == UNSUCCESSFUL) {
Pict->GenChildState = NOSIGSTATE;
} else {
Pict->GenChildState = GENINCOMPLETE;
if ( Pict->pNode.ln_Type == MANDPICT ) {
switch ( Pict->MathMode ) {
case 0:
MandelbrotInt32( Pict );
break;
case 2:
case 4:
MandelbrotIEEE( Pict );
break;
case 3:
MandelbrotInt32II( Pict );
break;
case 1: {
/*
* Constraints for IEEE to FFP conversion
*
* 1. SPFieee() expects 32 bit IEEE floats
* 2. The C language always promotes floats to doubles for
* parameter passing.
* 3. doubles are 64 bits wide
*
* Therefore I must do the following:
*
* 1. Convert double parameters to float
* 2. Take the address of the floats and cast them to *ULONG
* 3. Indirect off the ULONG pointers that are pointing to
* 32 IEEE format floats (gross eh?) as parameters to FFP
* Mandelbrot function.
*/
/* 32 bit IEEE float variables */
float StartX_float, StartY_float, GapX_float, GapY_float;
/* convert 64 bit IEEE variables into 32 bit IEEE variables */
StartX_float = Pict->RealLow;
StartY_float = Pict->ImagLow + Pict->CurLine*Pict->RealGap;
GapX_float = Pict->RealGap;
GapY_float = Pict->ImagGap;
/*
* calculate pointers and convert them to pointers to ULONG
* so that when we indirect off of these and pass the results
* as parameters they are not promoted to doubles.
*/
MandelbrotFFP( Pict,
*( (ULONG *) &StartX_float ),
*( (ULONG *) &StartY_float ),
*( (ULONG *) &GapX_float ),
*( (ULONG *) &GapY_float ));
}
break;
}
} else {
switch ( Pict->MathMode ) {
case 0:
case 3:
JuliaInt32( Pict );
break;
case 2:
case 4:
JuliaIEEE( Pict );
break;
case 1: {
/*
* Constraints for IEEE to FFP conversion
*
* 1. SPFieee() expects 32 bit IEEE float
* 2. The C language always promotes floats to doubles for
* parameter passing.
* 3. doubles are 64 bits wide
*
* Therefore I must do the following:
*
* 1. Convert double parameters to float
* 2. Take the address of the floats and cast them to *ULONG
* 3. Indirect off the ULONG pointers that are pointing to
* 32 IEEE format floats (gross eh?) as parameters to FFP
* Julia function.
*/
/* 32 bit IEEE float variables */
float JuliaX_float, JuliaY_float;
float StartX, StartY, GapX, GapY;
/* convert 64 bit IEEE variables into 32 bit IEEE variables */
JuliaX_float = Pict->Real;
JuliaY_float = Pict->Imag;
StartX = Pict->RealLow;
StartY = Pict->ImagLow;
GapX = Pict->RealGap;
GapY = Pict->ImagGap;
/*
* calculate pointers and convert them to pointers to ULONG
* so that when we indirect off of these and pass the results
* as parameters they are not promoted to doubles.
*/
JuliaFFP( Pict, *( (ULONG *) &JuliaX_float ),
*( (ULONG *) &JuliaY_float ),
*( (ULONG *) &StartX ),
*( (ULONG *) &StartY ),
*( (ULONG *) &GapX ),
*( (ULONG *) &GapY ) );
}
break;
}
}
Pict->GenChildState = GENCOMPLETE;
}
#ifdef MULTI
/* Indicate that generation has finished for this task */
Signal( mTask, mSigMask ); /* signal parent as to change */
while (Pict->GenState != KILLSTATE) { /* Wait for task to be removed */
while (Pict->GenState == GENERATESTATE) { /* spin 'till parent kills us */
}
/* accept any pauses that the parent may send too late */
if (Pict->GenState == PAUSESTATE) {
ChildSignal(Pict); /* signal back so parent doesn't hang */
}
}
/* We've been informed that we will die, so free up resources */
FreeSignal( Pict->gSigBit );
Signal( mTask, pSigMask ); /* signal death O.K. */
Wait( 0L ); /* stop here forever */
#endif
}
InitMand( Pict )
register struct Picture *Pict;
{
Pict->Real = 0.0;
Pict->Imag = 0.0;
}
SetWindowActive( Window, Active )
register struct Window *Window;
char Active;
{
struct Picture *Pict;
if ( Window ) {
Pict = (struct Picture *) Window->UserData;
if ( ! (Pict->Flags & BORDERLESS_PROJ)) {
Window->Title[0] = Active;
SetWindowTitles( Window, Window->Title, -1 );
}
}
}
/*
* Free up old memory and get memory for new picture
*/
GetCountsMemory( Pict )
register struct Picture *Pict;
{
/* free up old pictures iteration count pile */
FreeCounts( Pict );
/* Allocate memory for new picture */
Pict->CountsSize = Pict->CountX * Pict->CountY * sizeof(SHORT);
Pict->Counts = (SHORT *) safeAllocMem(Pict->CountsSize, MEMF_CLEAR );
if (Pict->Counts == NULL) {
Pict->CountsSize = Pict->CountX * sizeof(SHORT);
Pict->Counts = (SHORT *) safeAllocMem(Pict->CountsSize, MEMF_CLEAR);
if (Pict->Counts != NULL)
Pict->Flags |= NO_RAM_GENERATE;
} else {
Pict->Flags &= ~NO_RAM_GENERATE;
}
}
FreeCounts( Pict )
register struct Picture *Pict;
{
if ( Pict->Counts ) {
FreeMem( Pict->Counts, Pict->CountsSize );
Pict->Counts = NULL;
}
}
struct Gadget *
MakePictGads( Type )
register int Type;
{
register struct Gadget *gadget;
register struct Gadget *Newgadget;
register struct Gadget *Firstgadget;
register struct IntuiText *Intui;
register char *str;
struct Border *Border, *MakeShadow();
register int i,j,k;
struct IntuiText *ShadowIntui();
j = TOPMARG;
if ( Type == MANDPICT ) {
k = 4;
} else {
k = 5;
}
Firstgadget = NULL;
for (i = 0; i < k; i++) {
Newgadget = MakeBool(-15,j, 12,12, 0,(PICTTYPE<<WINDTYPEBITS)+i,NULL);
if (Newgadget) {
if ( i == 0 ) {
Firstgadget = Newgadget;
} else {
gadget->NextGadget = Newgadget;
}
Newgadget->Flags |= GRELRIGHT;
Newgadget->Activation |= RIGHTBORDER;
gadget = Newgadget;
j += 14;
switch( i ) {
case 0: str = "C"; break;
case 1: str = "G"; break;
case 2: str = "I"; break;
case 3: str = "O"; break;
case 4: str = "J"; break;
}
Intui = ShadowIntui( str, 3, 3);
if (Intui == NULL) {
FreeGadgets( Firstgadget );
}
gadget->GadgetText = Intui;
#define NUMPATCHCORNERS 5
Border = MakeShadow( NORMALPEN, NUMPATCHCORNERS );
if ( Border ) {
InitPatch( Border );
Border->NextBorder = (struct Border *) gadget->GadgetRender;
gadget->GadgetRender = (APTR) Border;
}
} else {
if (Firstgadget)
FreeGadgets( Firstgadget );
return( NULL );
}
}
return( Firstgadget );
}
SetGenGad( Pict )
register struct Picture *Pict;
{
register struct Window *Window;
register struct Gadget *Gadget;
register struct IntuiText *Intui;
register char c;
register int place;
if (Pict == NULL)
return;
if (Pict->Flags & BORDERLESS_PROJ)
return;
Window = Pict->Window;
if (Window) {
if ( Pict->gTask )
c = 'S';
else
c = 'G';
Gadget = Pict->Gadgets->NextGadget;
place = RemoveGadget( Window, Gadget );
Intui = Gadget->GadgetText;
Intui = Intui->NextText;
Intui->IText[0] = c;
Intui = Intui->NextText;
Intui->IText[0] = c;
AddGadget( Window, Gadget, place );
RefreshGadgets( Pict->Gadgets, Window, NULL );
}
}
InitPatch( Border )
register struct Border *Border;
{
register SHORT *NewCounts;
NewCounts = Border->XY;
*NewCounts++ = 3; *NewCounts++ = 11;
*NewCounts++ = 2; *NewCounts++ = 11;
*NewCounts++ = 2; *NewCounts++ = 2;
*NewCounts++ = 11; *NewCounts++ = 2;
*NewCounts++ = 11; *NewCounts++ = 3;
} /* InitPatch */
/*
* Open the Picture window
*/
OpenPicture( Pict )
struct Picture *Pict;
{
extern struct Window *OpenMyWind();
register struct Window *Window;
register struct NewWindow *NewWind;
register LONG width, height;
register LONG extrax,extray;
struct Gadget *gadgets, *MakePictGads();
if ( Pict->Window == NULL ) {
width = Pict->CountX;
height = Pict->CountY;
NewWind = Pict->NewWind;
if (Pict->Flags & BORDERLESS_PROJ) {
NewWind->Flags = ACTIVATE | REPORTMOUSE | NOCAREREFRESH |
SMART_REFRESH | BORDERLESS;
NewWind->Title = NULL;
Pict->Gadgets = gadgets = NULL;
if (Pict->LeftEdge+Pict->CountX+LEFTMARG+RIGHTMARG == screen->Width &&
Pict->TopEdge +Pict->CountY+TOPMARG+BOTMARG == screen->Height) {
Pict->LeftMarg = LEFTMARG;
Pict->RightMarg = RIGHTMARG;
Pict->TopMarg = TOPMARG;
Pict->BotMarg = BOTMARG;
} else {
Pict->LeftMarg = 0;
Pict->RightMarg = 0;
Pict->TopMarg = 0;
Pict->BotMarg = 0;
}
} else {
NewWind->Flags = WINDOWCLOSE | WINDOWDEPTH | WINDOWSIZING |
WINDOWDRAG | ACTIVATE | REPORTMOUSE | NOCAREREFRESH |
SMART_REFRESH;
NewWind->Title = (UBYTE *) Pict->Title;
Pict->Gadgets = gadgets = MakePictGads( Pict->pNode.ln_Type );
Pict->LeftMarg = LEFTMARG;
Pict->RightMarg = RIGHTMARG;
Pict->TopMarg = TOPMARG;
Pict->BotMarg = BOTMARG;
}
width += Pict->LeftMarg + Pict->RightMarg;
height += Pict->TopMarg + Pict->BotMarg;
extrax = width - screen->Width;
extray = height - screen->Height;
if ( extrax > 0 || extray > 0 ) {
ThrowTask( Pict);
FreeCounts( Pict);
DispErrMsg("Picture too big. Regenerate",0);
if ( extrax > 0 ) {
Pict->CountX -= extrax;
width -= extrax;
}
if ( extray > 0 ) {
Pict->CountY -= extray;
height -= extray;
}
}
NewWind->LeftEdge = Pict->LeftEdge;
NewWind->TopEdge = Pict->TopEdge;
Window = OpenMyWind(NewWind, screen, gadgets, width, height );
Pict->Window = Window;
if (Window == NULL) {
DispErrMsg("Can't open picture window",0);
FreeGadgets( Pict->Gadgets );
ThrowPict(Pict);
return( -1 );
} else {
CurWind = Window;
DisplayMsg();
SetAPen( Window->RPort, NORMALPEN );
if (Pict->Flags & BORDERLESS_PROJ) {
RectFill( Window->RPort, Pict->LeftMarg, Pict->TopMarg,
NewWind->Width-Pict->RightMarg-1,
NewWind->Height-Pict->BotMarg-1);
} else {
RectFill( Window->RPort, Pict->LeftMarg, Pict->TopMarg,
NewWind->Width, NewWind->Height);
}
Window->UserData = (BYTE *) Pict;
MoveResize( Pict->Window, &Pict->SizingGadget );
BorderWindow( Window );
if (Pict->CycleOn) {
CreateCycle();
}
}
}
SetGenGad( Pict );
return( 0 );
} /* OpenPicture */
MoveResize( Window, RetGadget )
register struct Window *Window;
register struct Gadget **RetGadget;
{
register struct Gadget *Gadget;
register int place;
Gadget = Window->FirstGadget;
while ( Gadget && !(Gadget->GadgetType & SIZING)) {
Gadget = Gadget->NextGadget;
}
if (Gadget) {
*RetGadget = Gadget;
place = RemoveGadget( Window, Gadget );
if (XScale == 0)
Gadget->LeftEdge -= 2;
if (YScale == 0)
Gadget->TopEdge -= 3;
else
Gadget->TopEdge -= 1;
AddGadget( Window, Gadget, place );
RefreshGList( Gadget, Window, NULL, 1);
}
}
/*
* Close the Mandelbrot Window
*/
ClosePicture( Pict )
register struct Picture *Pict;
{
register struct Window *Window;
register struct NewWindow *NewWindow;
if ( (Window = Pict->Window) != NULL) {
KillCycle();
FreeScrollTemp(Pict);
Pict->LeftEdge = Window->LeftEdge;
Pict->TopEdge = Window->TopEdge;
CloseMyWind(Window, Pict->Gadgets );
Pict->Window = NULL;
Pict->Gadgets = NULL;
Pict->Flags &= ~LENS_DISPLAYED;
}
}